home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The AGA Experience 3
/
AGA Experience Volume 3 (1997)(NFA - SAdENESS)[!].iso
/
software
/
utilities
/
graphics
/
raylab
/
source
/
texture.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-01
|
19KB
|
831 lines
/*
name: texture.c
Textures
--------
Texture-calculation and texture-handling.
This source-code is part of the RayLab 1.1 package, and it is provided
for your compiling pleasure. You may use it, change it, re-compile it
etc., as long as nobody else but you receive the changes/compilations
that you have made!
You may not use any part(s) of this source-code for your own productions
without the permission from the author of RayLab. Please read the legal
information found in the users documentation for RayLab for more details.
*/
#include <stdlib.h>
#include "defs.h"
#include "extern.h"
#define ntabsize 32 /* May be too big?? */
/* Use "global" noise table for noise functions (filled out with InitNoiseTable()) */
unsigned short noise_table[ntabsize][ntabsize][ntabsize];
void CreateDefTexture(TEXTURE *t)
{
t->CMap.Colors[0].r=1.0; t->CMap.Colors[0].g=0.3; t->CMap.Colors[0].b=0.0;
t->CMap.Colors[1].r=0.0; t->CMap.Colors[1].g=0.0; t->CMap.Colors[1].b=0.0;
t->CMap.Bounds[0]=0.0; t->CMap.Bounds[1]=1.0;
t->CMap.LastBound=1;
t->Pattern=PATTERN_NONE;
t->ImageType=IMG_NONE;
t->ImageNum=0;
t->Turbulence=0.0;
t->Reflect.r=t->Reflect.g=t->Reflect.b=0.0;
t->Filter.r=t->Filter.g=t->Filter.b=0.0;
t->Ior=1.0;
t->Ambient=0.2;
t->Diffuse=0.8;
t->Phong=0.3; t->PhongSize=10.0;
ClearTransform(&t->Transform);
}
void CopyTexture(TEXTURE *t2, TEXTURE *t1)
{
short i,lbound;
lbound=t1->CMap.LastBound;
for(i=0;i<=lbound;i++) {
t2->CMap.Bounds[i]=t1->CMap.Bounds[i];
CopyColor(&t2->CMap.Colors[i],&t1->CMap.Colors[i]);
}
t2->CMap.LastBound=lbound;
t2->Pattern=t1->Pattern;
t2->ImageType=t1->ImageType;
t2->ImageNum=t1->ImageNum;
t2->Turbulence=t1->Turbulence;
CopyColor(&t2->Reflect,&t1->Reflect);
CopyColor(&t2->Filter,&t1->Filter);
t2->Ior=t1->Ior;
t2->Ambient=t1->Ambient;
t2->Diffuse=t1->Diffuse;
t2->Phong=t1->Phong;
t2->PhongSize=t1->PhongSize;
CopyTransform(&t2->Transform,&t1->Transform);
}
void CopyColor(COLOR *c2, COLOR *c1)
{
c2->r=c1->r; c2->g=c1->g; c2->b=c1->b;
}
/**************************************************************
*
* Here are some useful (more or less) texture-patterns.
*
**************************************************************/
void GetSurfaceColor(COLOR *Color, TEXTURE *t, POINT *ip)
{
double MapValue;
int indx,foundindx;
COLORMAP *cm;
POINT temppoint,imgpoint;
RevTransformPoint(&temppoint,&t->Transform,ip); /* Transform point */
if(t->Turbulence>EPSILON) {
PTurbulence(&temppoint,&temppoint,t->Turbulence); /* Add some turbulence to the texture */
}
Color->r=-1.0;
if(t->ImageType!=IMG_NONE) { /* Image texture */
switch(t->ImageType) {
case IMG_24BIT:
RevTransformPoint(&imgpoint,&Img24Array[(int)t->ImageNum]->Transform,&temppoint);
GetImg24Color(Color,Img24Array[(int)t->ImageNum],&imgpoint);
break;
case IMG_8BIT:
RevTransformPoint(&imgpoint,&Img8Array[(int)t->ImageNum]->Transform,&temppoint);
GetImg8Color(Color,Img8Array[(int)t->ImageNum],&imgpoint);
break;
default:
break;
}
}
if(Color->r<0.0) { /* Normal builtin pattern */
switch(t->Pattern) { /* (also if outside of non-tiled image) */
case PATTERN_CHECKER:
MapValue=PatternChecker(&temppoint);
break;
case PATTERN_CIRCLES:
MapValue=PatternCircles(&temppoint);
break;
case PATTERN_RINGS:
MapValue=PatternRings(&temppoint);
break;
case PATTERN_SPOTS:
MapValue=PatternSpots(&temppoint);
break;
case PATTERN_GRADIENT:
MapValue=PatternGradient(&temppoint);
break;
case PATTERN_MARBLE:
MapValue=PatternMarble(&temppoint);
break;
case PATTERN_SOFTMARBLE:
MapValue=PatternSoftmarble(&temppoint);
break;
case PATTERN_SQUARES:
MapValue=PatternSquares(&temppoint);
break;
case PATTERN_BLURB:
MapValue=DNoise(&temppoint);
break;
case PATTERN_MANDEL:
MapValue=PatternMandel(&temppoint);
break;
case PATTERN_WOOD:
MapValue=PatternWood(&temppoint);
break;
case PATTERN_ANGULAR:
MapValue=PatternAngular(&temppoint);
break;
case PATTERN_NONE:
default:
MapValue=0.0;
break;
}
cm=&t->CMap;
foundindx=FALSE;
if(MapValue>EPSILON) {
indx=0;
while((indx<cm->LastBound)&&(foundindx==FALSE)) {
if((MapValue>=cm->Bounds[indx])&&(MapValue<=cm->Bounds[indx+1]))
foundindx=TRUE;
else indx++;
}
}
if(foundindx==TRUE) {
Color->r=(cm->Colors[indx].r*(cm->Bounds[indx+1]-MapValue)+cm->Colors[indx+1].r*(MapValue-cm->Bounds[indx]))/(cm->Bounds[indx+1]-cm->Bounds[indx]);
Color->g=(cm->Colors[indx].g*(cm->Bounds[indx+1]-MapValue)+cm->Colors[indx+1].g*(MapValue-cm->Bounds[indx]))/(cm->Bounds[indx+1]-cm->Bounds[indx]);
Color->b=(cm->Colors[indx].b*(cm->Bounds[indx+1]-MapValue)+cm->Colors[indx+1].b*(MapValue-cm->Bounds[indx]))/(cm->Bounds[indx+1]-cm->Bounds[indx]);
}
else {
Color->r=cm->Colors[0].r;
Color->g=cm->Colors[0].g;
Color->b=cm->Colors[0].b;
}
}
}
/**************************************************************
*
* Builtin patterns.
*
**************************************************************/
double PatternChecker(POINT *ip)
{
return( (double)(((long)floor(ip->x+EPSILON)+(long)floor(ip->y+EPSILON)+(long)floor(ip->z+EPSILON))&1L) );
}
double PatternCircles(POINT *ip)
{
return(fmod(sqrt(ip->x*ip->x+ip->y*ip->y+ip->z*ip->z),1.0));
}
double PatternRings(POINT *ip)
{
return(fmod(sqrt(ip->x*ip->x+ip->y*ip->y),1.0));
}
double PatternSpots(POINT *ip)
{
double d;
POINT dgrid;
dgrid.x=ip->x-floor(ip->x+0.5);
dgrid.y=ip->y-floor(ip->y+0.5);
dgrid.z=ip->z-floor(ip->z+0.5);
d=2.0*sqrt(dgrid.x*dgrid.x+dgrid.y*dgrid.y+dgrid.z*dgrid.z);
if(d>1.0) d=1.0;
return(d);
}
double PatternGradient(POINT *ip)
{
return(fmod((ip->z+50000.0),1.0));
}
double PatternMarble(POINT *ip)
{
double d,dnoise,ret;
int i;
POINT tp;
tp.x=ip->x*10.0;
tp.y=ip->y*5.0;
tp.z=ip->z*5.0;
dnoise=DNoise(&tp);
d=(ip->x+50000)*17.0+7.0*dnoise;
i=((int)floor(d))%17;
if(i<4) {
tp.x=ip->x*14.3;
tp.y=ip->y*20.0;
tp.z=ip->z*20.0;
ret=0.7+0.2*DNoise(&tp);
}
else if((i<9)||(i>12)) {
tp.x=ip->x*10.0;
tp.y=ip->y*10.0;
tp.z=ip->z*10.0;
d=fabs(d-floor(d*0.05882)*17-10.5)*0.1538462;
ret=0.4+0.3*d+0.2*DNoise(&tp);
} else
ret=0.2+0.2*dnoise;
ret = (ret > 1.0 ? 1.0 : ret); /* 0.0 <= ret <= 1.0 */
return(ret);
}
double PatternSoftmarble(POINT *ip)
{
register double d,ret;
POINT tp;
tp.x = ip->x*10.0;
tp.y = ip->y*5.0;
tp.z = ip->z*5.0;
d = (ip->x+50000)*17.0+7.0*DNoise(&tp);
ret = fmod(d,17.0)*0.117647; /* /8.5 */
if(ret>1.0) ret = 2.0-ret; /* 0.0 <= ret <= 1.0 */
tp.x = ip->x*(10+4*ret);
tp.y = ip->y*(5+15*ret);
tp.z = ip->z*(5+15*ret);
ret = 0.7*ret + 0.3*DNoise(&tp);
if(ret>1.0) ret = 1.0;
return(1.0-ret);
}
double PatternSquares(POINT *ip)
{
double d;
POINT dgrid;
dgrid.x=ip->x-0.5;
dgrid.y=ip->y-0.5;
dgrid.z=ip->z-0.5;
dgrid.x=2.0*fabs(dgrid.x-floor(ip->x));
dgrid.y=2.0*fabs(dgrid.y-floor(ip->y));
dgrid.z=2.0*fabs(dgrid.z-floor(ip->z));
d=dgrid.x;
if(dgrid.y<d) d=dgrid.y;
if(dgrid.z<d) d=dgrid.z;
if(d>1.0) d=1.0;
return(1.0-d);
}
double PatternMandel(POINT *ip)
{
register double za,zb,ca,cb;
register double d,rmax;
register int i;
za=zb=0.0;
ca=ip->x; cb=ip->y;
rmax=4.0;
for(i=100;i>0;i--) {
d=2.0*za*zb;
za*=za; zb*=zb;
if((za+zb)>rmax) break;
za=za-zb+ca; zb=d+cb; /* z = z*z + c */
}
return((double)i/(double)100.0);
}
double PatternWood(POINT *ip)
{
double r, angle;
r=sqrt(ip->x*ip->x + ip->y*ip->y);
if(ip->y==0.0) angle=PID2;
else angle=atan(ip->x/ip->y);
r+=0.08*sin(20.0*angle + ip->z);
return(fmod(r,1.0));
}
double PatternAngular(POINT *ip)
{
double angle;
if(ip->x==0.0) {
if(ip->y>0.0) angle=PID2;
else angle=-PID2;
}
else {
angle=atan(ip->y/ip->x);
if(ip->x<0.0) angle+=PI;
}
angle=fmod((angle+PIM2)*(1.0/PIM2),1.0);
return(angle);
}
/**************************************************************
*
* Image texture functions.
*
**************************************************************/
void GetImg24Color(COLOR *Col,IMAGE24 *Image,POINT *ip)
{
double du,dv,x,y;
int u,v;
register int u2,v2;
register int XSize,YSize;
COLOR a,b,c,d;
unsigned char *Body,*Col24;
XSize=Image->XSize; YSize=Image->YSize;
switch(Image->Maptype) {
case MAP_SPHERICAL:
MapSpherical(ip->x,ip->y,ip->z,&x,&y);
x*=(double)XSize/PIM2;
y*=(double)YSize/PI;
break;
case MAP_CYLINDRICAL:
x=MapCylindrical(ip->x,ip->y)*(double)XSize/PIM2;
if(Image->Tile==TILE_TRUE)
y=(double)YSize*(50000.0-ip->z);
else {
if((ip->z<1.0)&&(ip->z>0.0))
y=(double)YSize*(1.0-ip->z);
else
x=-1.0;
}
break;
case MAP_PLANAR:
default:
if(Image->Tile==TILE_TRUE) {
x=(double)XSize*(ip->x+50000.0); y=(double)YSize*(50000-ip->y);
}
else {
if((ip->x<1.0)&&(ip->x>0.0)&&(ip->y<1.0)&&(ip->y>0.0)) {
x=(double)XSize*(ip->x); y=(double)YSize*(1.0-ip->y);
}
else x=-1.0;
}
break;
}
if(x>=0.0) {
u=(int)floor(x); v=(int)floor(y);
du=x-(double)u; dv=y-(double)v;
u2=(u+1)%XSize; v2=(v+1)%YSize;
u=u%XSize; v=v%YSize;
Body=Image->Body;
if(Image->Interpolate==INTPOL_NONE) {
Col24=&Body[3*(u+(v*XSize))];
Col->r=((double)*Col24++)*0.003921568; /* <=> divide by 255.0 */
Col->g=((double)*Col24++)*0.003921568;
Col->b=((double)*Col24)*0.003921568;
}
else {
Col24=&Body[3*(u+(v*XSize))];
a.r=((double)*Col24++)*0.003921568; /* <=> divide by 255.0 */
a.g=((double)*Col24++)*0.003921568;
a.b=((double)*Col24)*0.003921568;
Col24=&Body[3*(u2+(v*XSize))];
b.r=((double)*Col24++)*0.003921568;
b.g=((double)*Col24++)*0.003921568;
b.b=((double)*Col24)*0.003921568;
Col24=&Body[3*(u+(v2*XSize))];
c.r=((double)*Col24++)*0.003921568;
c.g=((double)*Col24++)*0.003921568;
c.b=((double)*Col24)*0.003921568;
Col24=&Body[3*(u2+(v2*XSize))];
d.r=((double)*Col24++)*0.003921568;
d.g=((double)*Col24++)*0.003921568;
d.b=((double)*Col24)*0.003921568;
InterpolateLinear(Col,&a,&b,&c,&d,du,dv);
}
}
else {
Col->r=-1.0;
}
}
void GetImg8Color(COLOR *Col,IMAGE8 *Image,POINT *ip)
{
double du,dv,x,y;
int u,v;
register int u2,v2;
register int XSize,YSize;
COLOR a,b,c,d,*CMap;
unsigned char *Body;
XSize=Image->XSize; YSize=Image->YSize;
switch(Image->Maptype) {
case MAP_SPHERICAL:
MapSpherical(ip->x,ip->y,ip->z,&x,&y);
x*=(double)XSize/PIM2;
y*=(double)YSize/PI;
break;
case MAP_CYLINDRICAL:
x=MapCylindrical(ip->x,ip->y)*(double)XSize/PIM2;
if(Image->Tile==TILE_TRUE)
y=(double)YSize*(50000.0-ip->z);
else {
if((ip->z<1.0)&&(ip->z>0.0))
y=(double)YSize*(1.0-ip->z);
else
x=-1.0;
}
break;
case MAP_PLANAR:
default:
if(Image->Tile==TILE_TRUE) {
x=(double)XSize*(ip->x+50000.0); y=(double)YSize*(50000-ip->y);
}
else {
if((ip->x<1.0)&&(ip->x>0.0)&&(ip->y<1.0)&&(ip->y>0.0)) {
x=(double)XSize*(ip->x); y=(double)YSize*(1.0-ip->y);
}
else {
x=-1.0;
}
}
break;
}
if(x>=0.0) {
u=(int)floor(x); v=(int)floor(y);
du=x-(double)u; dv=y-(double)v;
u2=(u+1)%XSize; v2=(v+1)%YSize;
u=u%XSize; v=v%YSize;
Body=Image->Body;
CMap=Image->Colormap;
if(Image->Interpolate==INTPOL_NONE) {
*Col=CMap[(int)Body[u+v*XSize]];
}
else {
a=CMap[(int)Body[u+v*XSize]];
b=CMap[(int)Body[u2+v*XSize]];
c=CMap[(int)Body[u+v2*XSize]];
d=CMap[(int)Body[u2+v2*XSize]];
InterpolateLinear(Col,&a,&b,&c,&d,du,dv);
}
}
else {
Col->r=-1.0;
}
}
void MapSpherical(double x, double y, double z, double *u, double *v)
{
register double r;
*u=MapCylindrical(x,y);
r=sqrt(x*x+y*y+z*z);
if(r>0.0) *v=acos(z/r);
else *v=0.0;
}
double MapCylindrical(double x, double y)
{
register double r,a,b,u;
short quadrant;
quadrant=0;
if(x<0) {
quadrant++;
if(y<0) quadrant++;
}
else if(y<0) quadrant=3;
r=sqrt(x*x+y*y);
if(r>0.0) {
a=fabs(x); b=fabs(y);
if(a>b) u=acos(a/r);
else u=asin(b/r);
switch(quadrant) {
case 0:
break;
case 1:
u=PI-u;
break;
case 2:
u+=PI;
break;
case 3:
u=PIM2-u;
break;
}
}
else u=0.0;
return(u);
}
void InterpolateLinear(COLOR *Col, COLOR *a, COLOR *b, COLOR *c, COLOR *d, double du, double dv)
{
register double dudv;
dudv=du*dv;
Col->r = a->r + du*(b->r - a->r) + dv*(c->r - a->r) + dudv*(a->r - b->r - c->r + d->r);
Col->g = a->g + du*(b->g - a->g) + dv*(c->g - a->g) + dudv*(a->g - b->g - c->g + d->g);
Col->b = a->b + du*(b->b - a->b) + dv*(c->b - a->b) + dudv*(a->b - b->b - c->b + d->b);
}
/**************************************************************
*
* Noise functions.
*
**************************************************************/
void InitNoiseTable(void)
{
int x,y,z,xx,yy,zz;
RndSeed=3426516L; /* Ensures same table every time, on all platforms */
for(x=0;x<ntabsize;x++) {
for(y=0;y<ntabsize;y++) {
for(z=0;z<ntabsize;z++) {
noise_table[x][y][z]=(unsigned short)floor((Jitter()+1.0)*16383.5); /* Values range from 0 to 32767 */
if(x>=(ntabsize-1)) xx=0;
else xx=x;
if(y>=(ntabsize-1)) yy=0;
else yy=y;
if(z>=(ntabsize-1)) zz=0;
else zz=z;
noise_table[x][y][z]=noise_table[xx][yy][zz];
}
}
}
}
/*
*
* DNoise() returns a float (double) value between 0.0 and 1.0
*
*/
double DNoise(POINT *ip)
{
register int ix,iy,iz;
register unsigned short n[8];
register double ox,oy,oz;
double px,py,pz;
double n00,n01,n10,n11;
double n0,n1,n2;
px=ip->x-mincoord; /* Offset x,y,z to ensure they are positive */
py=ip->y-mincoord;
pz=ip->z-mincoord;
ix=(int)px;
iy=(int)py;
iz=(int)pz;
ix=ix%(ntabsize-1);
iy=iy%(ntabsize-1);
iz=iz%(ntabsize-1);
ox=px-floor(px);
oy=py-floor(py);
oz=pz-floor(pz);
/* interpolate to get noise value at (ix+ox,iy+oy,iz+oz) */
n[0]=noise_table[ix][iy][iz];
n[1]=noise_table[ix][iy][iz+1];
n[2]=noise_table[ix][iy+1][iz];
n[3]=noise_table[ix][iy+1][iz+1];
n[4]=noise_table[ix+1][iy][iz];
n[5]=noise_table[ix+1][iy][iz+1];
n[6]=noise_table[ix+1][iy+1][iz];
n[7]=noise_table[ix+1][iy+1][iz+1];
n00=n[0]+ox*(n[4]-n[0]);
n01=n[1]+ox*(n[5]-n[1]);
n10=n[2]+ox*(n[6]-n[2]);
n11=n[3]+ox*(n[7]-n[3]);
n0=n00+oy*(n10-n00);
n1=n01+oy*(n11-n01);
n2=(n0+oz*(n1-n0))*0.000030518; /* 0.0 <= value <= 1.0 */
/* n=noise_table[ix][iy][iz];
n00=n+ox*(noise_table[ix+1][iy][iz]-n);
n=noise_table[ix][iy][iz+1];
n01=n+ox*(noise_table[ix+1][iy][iz+1]-n);
n=noise_table[ix][iy+1][iz];
n10=n+ox*(noise_table[ix+1][iy+1][iz]-n);
n=noise_table[ix][iy+1][iz+1];
n11=n+ox*(noise_table[ix+1][iy+1][iz+1]-n); */
if(n2<0.0) n2=0.0;
else if(n2>1.0) n2=1.0;
return(n2);
}
/*
*
* VNoise() returns a vector (v, |v| = 1) given a point p1
*
*/
void VNoise(VECTOR *v, POINT *p1)
{
register int ix,iy,iz;
register unsigned short n;
register double ox,oy,oz;
double px,py,pz;
double n00,n01,n10,n11;
register double n0,n1,f;
f=0.000061037;
px=p1->x+50000.0; /* Offset x,y,z to ensure they are positive */
py=p1->y+50000.0;
pz=p1->z+50000.0;
ix=((int)floor(px))%(ntabsize-1);
iy=((int)floor(py))%(ntabsize-1);
iz=((int)floor(pz))%(ntabsize-1);
ox=px-floor(px);
oy=py-floor(py);
oz=pz-floor(pz);
/* interpolate to get noise value at (ix+ox,iy+oy,iz+oz) */
n=noise_table[ix][iy][iz];
n00=n+ox*(noise_table[ix+1][iy][iz]-n);
n=noise_table[ix][iy][iz+1];
n01=n+ox*(noise_table[ix+1][iy][iz+1]-n);
n=noise_table[ix][iy+1][iz];
n10=n+ox*(noise_table[ix+1][iy+1][iz]-n);
n=noise_table[ix][iy+1][iz+1];
n11=n+ox*(noise_table[ix+1][iy+1][iz+1]-n);
n0=n00+oy*(n10-n00); n1=n01+oy*(n11-n01); v->x=1.0-(n0+oz*(n1-n0))*f; /* -1.0 <= v-x <= 1.0 */
ix=(ix+5)%(ntabsize-1); iy=(iy+5)%(ntabsize-1); iz=(iz+5)%(ntabsize-1);
n=noise_table[ix][iy][iz];
n00=n+ox*(noise_table[ix+1][iy][iz]-n);
n=noise_table[ix][iy][iz+1];
n01=n+ox*(noise_table[ix+1][iy][iz+1]-n);
n=noise_table[ix][iy+1][iz];
n10=n+ox*(noise_table[ix+1][iy+1][iz]-n);
n=noise_table[ix][iy+1][iz+1];
n11=n+ox*(noise_table[ix+1][iy+1][iz+1]-n);
n0=n00+oy*(n10-n00); n1=n01+oy*(n11-n01); v->y=1.0-(n0+oz*(n1-n0))*f;
ix=(ix+5)%(ntabsize-1); iy=(iy+5)%(ntabsize-1); iz=(iz+5)%(ntabsize-1);
n=noise_table[ix][iy][iz];
n00=n+ox*(noise_table[ix+1][iy][iz]-n);
n=noise_table[ix][iy][iz+1];
n01=n+ox*(noise_table[ix+1][iy][iz+1]-n);
n=noise_table[ix][iy+1][iz];
n10=n+ox*(noise_table[ix+1][iy+1][iz]-n);
n=noise_table[ix][iy+1][iz+1];
n11=n+ox*(noise_table[ix+1][iy+1][iz+1]-n);
n0=n00+oy*(n10-n00); n1=n01+oy*(n11-n01); v->z=1.0-(n0+oz*(n1-n0))*f;
NormalizeVector(v,v); /* Normalize v */
}
/*
*
* PTurbulence() makes a random walk of 4 steps
*
*/
void PTurbulence(POINT *p2, POINT *p1, double Factor)
{
int i;
double l,o;
VECTOR tmp1, tmp2, tmp0;
tmp2.x=tmp2.y=tmp2.z=0.0;
VNoise(&tmp0,p1);
l=2.0; o=0.5;
for (i=2; i<=6; i++) {
tmp1.x=l*p1->x;
tmp1.y=l*p1->y;
tmp1.z=l*p1->z;
VNoise(&tmp2,(POINT *)&tmp1);
tmp0.x+=o*tmp2.x;
tmp0.y+=o*tmp2.y;
tmp0.z+=o*tmp2.z;
if (i<6) {
l*=2.0;
o*=0.5;
}
}
tmp0.x*=Factor; tmp0.y*=Factor; tmp0.z*=Factor;
AddVector((VECTOR *)p2, (VECTOR *)p1, &tmp0);
}
/*****************************************************************
*
* Transform point to objects original orientation
*
*****************************************************************/
void RevTransformPoint(POINT *ReTransformedPoint, TRANSFORM *Transform, POINT *Point)
{
VECTOR tempv;
register int i;
double d,a,b,x,y;
*ReTransformedPoint=*Point;
if(Transform->NumTransforms>0) { /* Retransform the surface point */
for(i=Transform->NumTransforms-1;i>=0;i--) {
switch(Transform->Entry[i].Type) {
case TRANSFORM_SCALE:
ReTransformedPoint->x=ReTransformedPoint->x/Transform->Entry[i].Values.x;
ReTransformedPoint->y=ReTransformedPoint->y/Transform->Entry[i].Values.y;
ReTransformedPoint->z=ReTransformedPoint->z/Transform->Entry[i].Values.z;
break;
case TRANSFORM_MOVE:
ReTransformedPoint->x-=Transform->Entry[i].Values.x;
ReTransformedPoint->y-=Transform->Entry[i].Values.y;
ReTransformedPoint->z-=Transform->Entry[i].Values.z;
break;
case TRANSFORM_ROTATE:
NegVector(&tempv,&Transform->Entry[i].Values);
RevRotatePoint(ReTransformedPoint,&tempv);
break;
case TRANSFORM_WHIRL:
x=ReTransformedPoint->x;
y=ReTransformedPoint->y;
d=Transform->Entry[i].Values.x-sqrt(x*x+y*y);
if(d>0) {
d*=-d*Transform->Entry[i].Values.y;
a=cos(d); b=sin(d);
ReTransformedPoint->x=a*x-b*y;
ReTransformedPoint->y=b*x+a*y;
}
break;
case TRANSFORM_TWIST:
d=ReTransformedPoint->z*Transform->Entry[i].Values.x;
x=ReTransformedPoint->x;
y=ReTransformedPoint->y;
a=cos(d); b=sin(d);
ReTransformedPoint->x=a*x-b*y;
ReTransformedPoint->y=b*x+a*y;
break;
case TRANSFORM_NONE:
default:
break;
}
}
}
}